package com.guodi.model.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guodi.common.constant.StatusCode;
import com.guodi.common.utils.AjaxResult;
import com.guodi.common.utils.Asserts;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.boot.ctrl.BaseController;
import com.guodi.core.minio.util.MinioUtil;
import com.guodi.core.tool.api.R;
import com.guodi.model.entity.CmeReport;
import com.guodi.model.service.ICmeReportService;
import com.guodi.model.service.IIdtMonitorValueService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;

/**
 * @描述：体检报告管理表控制类
 * @作者: 徐金洲
 * @日期: 2023-04-07
 */
@RestController
@RequestMapping("/CmeReport")
@Api(value = "API - CmeReportController", tags = "体检报告管理表")
public class CmeReportController extends BaseController {

    @Resource
    public ICmeReportService cmeReportService;

    @Resource
    private IIdtMonitorValueService idtMonitorValueService;


    /**
     * @描述: 检验是否有同名的评估报告
     * @入参: divisionCode 行政区划编码
     * @入参: year 年份
     * @出参: R
     * @作者: 徐金洲
     * @日期: 2023-04-27
     **/
    @PostMapping("/checkReportName")
    @ApiOperation(value = "检验是否有同名的评估报告")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "divisionCode", value = "区域编码", required = true,  dataType = "string", paramType = "query",example = "4301"),
            @ApiImplicitParam(name = "year", value = "指标数值年份", required = true, dataType = "string", paramType = "query",example = "2023")
    })
    public R checkReportName(String divisionCode, Integer year) {
        //获取行政区划名称
        String divisionText = idtMonitorValueService.getNameByDivisionCode(divisionCode);
        try{
            //拼接文件名,用于校验是否有同名的体检评估报告
            String newExportFileName = year.toString()+ "年" + divisionText +"城市体检评估报告" ;
            //查询该体检评估报告是否已存在
            LambdaQueryWrapper<CmeReport> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CmeReport::getReportName, newExportFileName);
            List<CmeReport> list = cmeReportService.list(queryWrapper);
            if (list.size() > 0) {
                boolean isExist = true;
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("isExist",isExist);
                return R.data(200,jsonObject,"已存在" + divisionText + year.toString() + "年体检评估报告!");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.success("");
    }

    /**
     * @描述: 导出【体检评估预警报告】word报告
     * @入参: CmeReport
     * @出参: boolean
     * @作者: 徐金洲
     * @日期: 2023-04-10
     **/
    @PostMapping("/generateCmeReport")
    @ApiOperation(value = "生成体检评估word报告")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "indicatorsTypeCode", value = "指标体系编码", required = true, dataType = "string", paramType = "query",example = "city-county-plan"),
            @ApiImplicitParam(name = "divisionCode", value = "区域编码", required = true,  dataType = "string", paramType = "query",example = "3201"),
            @ApiImplicitParam(name = "year", value = "指标数值年份", required = true, dataType = "string", paramType = "query",example = "2019"),
            @ApiImplicitParam(name = "orgId", value = "机构id", required = true, dataType = "string", paramType = "query",example = "65fc1451aa4640c795b971ae9199456c"),
            @ApiImplicitParam(name = "particularYear", value = "指标体系年份", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "imageArray", value = "地图图片路径", required = true, dataType = "string", paramType = "query")
    })
    public R generateCmeReport(HttpServletResponse response, String indicatorsTypeCode, String divisionCode, Integer year,
                               String orgId, String particularYear, String imageArray) {
        try{
            //初始化报告管理数据(例如:创建时间,创建人等)
            CmeReport cmeReport = new CmeReport();
            prepareData(cmeReport,true);
            //生成报告
            cmeReportService.generateCmeReport(response, indicatorsTypeCode, divisionCode, year, orgId, particularYear, cmeReport, imageArray);
        }catch (Exception e){
            e.printStackTrace();
        }
        return R.success("体检评估报告生成成功!");
    }


    /**
     * @描述: 导出【体检评估预警报告】word报告
     * @入参: CmeReport
     * @出参: boolean
     * @作者: 徐金洲
     * @日期: 2023-04-10
     **/
    @PostMapping("/exportCmeReport")
    @ApiOperation(value = "导出【体检评估预警报告】word报告")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "indicatorsTypeCode", value = "指标体系编码", required = true, dataType = "string", paramType = "query",example = "city-county-plan"),
            @ApiImplicitParam(name = "divisionCode", value = "区域编码", required = true,  dataType = "string", paramType = "query",example = "3201"),
            @ApiImplicitParam(name = "year", value = "指标数值年份", required = true, dataType = "string", paramType = "query",example = "2019"),
            @ApiImplicitParam(name = "orgId", value = "机构id", required = true, dataType = "string", paramType = "query",example = "65fc1451aa4640c795b971ae9199456c"),
            @ApiImplicitParam(name = "particularYear", value = "指标体系年份", required = true, dataType = "string", paramType = "query")
    })
    public R exportCmeReport(HttpServletResponse response, String indicatorsTypeCode, String divisionCode, Integer year,
                                String orgId, String particularYear) throws IOException {
        try{
            CmeReport cmeReport = new CmeReport();
            prepareData(cmeReport,true);
            boolean temp = cmeReportService.exportCmeReportReport(response, indicatorsTypeCode, divisionCode, year, orgId, particularYear, cmeReport);
            if(temp){
                return R.fail("该体检评估报告已存在!");
            }
        }catch (Exception e){
            AjaxResult ajaxResult = new AjaxResult(StatusCode.ERROR_CODE_40005, "导出失败");
            response.setContentType("application/json;charset=UTF-8;");
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(JSON.toJSONString(ajaxResult).getBytes("UTF-8"));
            outputStream.flush();
            outputStream.close();
        }
        return R.success("体检评估报告生成成功!");
    }


    /**
     * @描述: 上传体检报告
     * @入参: CmeReport
     * @出参: boolean
     * @作者: 徐金洲
     * @日期: 2023-04-07
     **/
    @PostMapping("/uploadFile")
    @ApiOperation(value = "上传体检报告")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "体检报告文件", required = true, dataType = "file", paramType = "query")
    })
    public R uploadFile(CmeReport cmeReport, MultipartFile file) throws IOException {
        Asserts.isEmpty(file, "体检报告文件必传");
        List<CmeReport> list = null;
        //如果 reportName 不为空就是要修改报告名再提交的
        if(org.apache.commons.lang.StringUtils.isNotBlank(cmeReport.getReportName())){
            String reportName = cmeReport.getReportName();
            cmeReport.setReportName(reportName);
            //查询是否有重复报告名称的数据
            LambdaQueryWrapper<CmeReport> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CmeReport::getReportName, reportName);
            list = cmeReportService.list(queryWrapper);
        }else {
            //获取文件名
            String fileName = file.getOriginalFilename();
            //文件名去除后缀
            String filename = fileName.substring(0, fileName.lastIndexOf("."));
            //拼接报告名称
            String reportName = cmeReport.getYear() + "年" + cmeReport.getDivisionName() + filename;
            cmeReport.setReportName(reportName);
            //查询是否有重复报告名称的数据
            LambdaQueryWrapper<CmeReport> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CmeReport::getReportName, reportName);
            list = cmeReportService.list(queryWrapper);
        }
        if (list.size() > 0) {
            boolean isRepeat = true;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("isRepeat",isRepeat);
            return R.data(200,jsonObject,"");
        }else {
            prepareData(cmeReport, true);
            cmeReportService.uploadFile(cmeReport,file);
        }
        return R.success("体检报告上传成功!");
    }


    /**
     * @描述: 下载体检评估报告
     * @入参: id
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-03-09
     **/
    @PostMapping("/download")
    @ApiOperation(value = "下载附件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileUrl", value = "体检报告pdfUrl", required = true,dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "type", value = "类型", required = true,dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "reportName", value = "体检报告名称", required = true,dataType = "string", paramType = "query")
    })
    public R download(String fileUrl, String type, String reportName, HttpServletResponse response) throws IOException {
        InputStream inputStream = null;
        if(type.equals("word")){
            inputStream = MinioUtil.download(fileUrl);
        }else if(type.equals("pdf")){
            inputStream = MinioUtil.download(fileUrl);
        }
        ServletOutputStream outputStream = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(reportName + ".docx", "UTF-8"));
            outputStream = response.getOutputStream();
            int len = 0;
            byte[] buf = new byte[10240];
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, len);
            }
            outputStream.flush();
            R.success("下载成功");
        } catch (IOException e) {
            e.printStackTrace();
            R.fail("下载失败");
        } finally {
            outputStream.close();
        }
        return R.success("下载成功");
    }


    /**
     * @描述: 分页查询列表
     * @入参: CmeReport
     * @出参: page
     * @作者: 徐金洲
     * @日期: 2023-04-07
     **/
    @PostMapping("/list")
    @ApiOperation(value = "分页查询列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "页数", required = true, dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "size", value = "查询数量", required = true, dataType = "int", paramType = "query")
    })
    public R list(Page page, String divisionCode, String year, String month, String createTime, String reportName) {
        page = cmeReportService.listByEntity(page, divisionCode, year, month, createTime, reportName);
        return R.data(page);
    }


    /**
     * @描述: 新增体检报告管理信息
     * @入参: CmeReport
     * @出参: boolean
     * @作者: 徐金洲
     * @日期: 2023-04-07
     **/
    @PostMapping("/save")
    @ApiOperation(value = "新增")
    public R save(@Valid CmeReport cmeReport) {
        prepareData(cmeReport,true);
        cmeReport.setId(UuidUtil.get32UUID());
        boolean temp = cmeReportService.save(cmeReport);
        if (temp) {
            return R.success("新增成功");
        }
        return R.fail("新增失败");
    }


    /**
     * @描述: 删除体检报告管理信息
     * @入参: CmeReport
     * @出参: boolean
     * @作者: 徐金洲
     * @日期: 2023-04-13
     **/
    @PostMapping("/delete")
    @ApiOperation(value = "删除")
    @ApiImplicitParam(name = "ids", value = "主键id，如果多个，英文逗号隔开", required = true, dataType = "string", paramType = "query")
    public R delete(String ids) {
        if (StringUtils.isBlank(ids)) {
            return R.fail("id不能为空!");
        }
        //将英文逗号分隔的字符串 id 转成 list
        List<String> idList = Arrays.asList(ids.trim().split(","));
        //先删除mino上传的文件
        LambdaQueryWrapper<CmeReport> queryWrapper = (new QueryWrapper()).lambda();
        if (idList.size() > 0) {
            queryWrapper.in(CmeReport::getId, idList);
            List<CmeReport> list = cmeReportService.list(queryWrapper);
            for (CmeReport cmeReport : list) {
                String docUrl = cmeReport.getWordFilePath();
                String pdfUrl = cmeReport.getPdfFilePath();
                List<String> fileUrlList = new ArrayList<>();
                fileUrlList.add(docUrl);
                fileUrlList.add(pdfUrl);
                MinioUtil.batchRemoveFile(fileUrlList);
            }
            //再删除体检评估报告信息
            boolean temp = cmeReportService.removeByIds(idList);
            if (temp) {
                return R.success("删除成功!");
            }
        }
        return R.fail("删除失败!");
    }


    /**
     * @描述: 上传地图生成的图片返回 minio 地址
     * @入参: file
     * @出参: String url
     * @作者: 徐金洲
     * @日期: 2023-04-24
     **/
    @PostMapping("/uploadImage")
    @ApiOperation(value = "上传地图生成的图片")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "上传地图生成的图片", required = true, dataType = "file", paramType = "query")
    })
    public R uploadImage(MultipartFile[] file) throws IOException {
        Asserts.isEmpty(file, "图片文件必传");
        //图片路径
        String imageUrl = "";
        //uuid 用于区分图片目录
        String uuid = UuidUtil.get32UUID();
        //定义返回文件的 map,用于存储文件路径
        String imageArrar[] = new String[file.length];
        //获取文件名
        for(int i = 0; i < file.length; i++){
            String filename = file[i].getOriginalFilename();
            imageUrl = MinioUtil.uploadFile(file[i].getInputStream(), "mapimage/" + uuid,filename+".png");
            imageArrar[i] = imageUrl;
        }
        return R.data(imageArrar);
    }


    private void prepareData(CmeReport cmeReport, boolean isSave) {
        if(isSave){
            cmeReport.setCreator(this.getUser().getUserId().toString());
            cmeReport.setCreateTime(new Date());
            //防止误修改
            cmeReport.setModifier(null);
            cmeReport.setModifyTime(null);
        }else{
            cmeReport.setModifier(this.getUser().getUserId().toString());
            cmeReport.setModifyTime(new Date());
            //防止误修改
            cmeReport.setCreator(null);
            cmeReport.setCreateTime(null);
        }
    }
}
